#include "cmsis_mem.h"
#include "cmsis_os.h"
#include "tlsf.h"

static void * tlsf_handle = NULL;
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];

/**
 * @description:
 * @return {*}
 */
static tlsf_t cmsis_mem_tlsf_get(void)
{
    return (tlsf_t)tlsf_handle;
}

/**
 * @description:
 * @param {void *} tlsf
 * @return {*}
 */
static void cmsis_mem_tlsf_set(void * tlsf)
{
    tlsf_handle = tlsf;
}

/**
 * @description:
 * @return {*}
 */
void cmsis_mem_tlsf_init(void)
{
    tlsf_handle = tlsf_create(ucHeap);
    osAssert(!tlsf_handle);

    cmsis_mem_tlsf_set(tlsf_handle);
    tlsf_check(tlsf_handle);
}

/**
 * @description:
 * @param {size_t} bytes
 * @return {*}
 */
void* cmsis_mem_tlsf_malloc(size_t bytes)
{
    if (!cmsis_mem_tlsf_get())
    {
        cmsis_mem_tlsf_init();
    }

    return tlsf_malloc(cmsis_mem_tlsf_get(), bytes);
}

/**
 * @description:
 * @param {tlsf_t} tlsf
 * @param {size_t} align
 * @param {size_t} bytes
 * @return {*}
 */
void* cmsis_mem_tlsf_memalign(size_t align, size_t bytes)
{
    osAssert(!cmsis_mem_tlsf_get());
    return tlsf_memalign(cmsis_mem_tlsf_get(), align, bytes);
}

/**
 * @description:
 * @param {tlsf_t} tlsf
 * @param {void*} ptr
 * @param {size_t} size
 * @return {*}
 */
void* cmsis_mem_tlsf_realloc(void* ptr, size_t size)
{
    osAssert(!cmsis_mem_tlsf_get());
    return tlsf_realloc(cmsis_mem_tlsf_get(), ptr, size);
}

/**
 * @description:
 * @param {tlsf_t} tlsf
 * @param {void*} ptr
 * @return {*}
 */
void cmsis_mem_tlsf_free(void* ptr)
{
    osAssert(!cmsis_mem_tlsf_get());
    tlsf_free(cmsis_mem_tlsf_get(), ptr);
}
